package com.user.filter;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.user.config.JwtProperties;
import com.user.entity.Role;
import com.user.entity.UserInfo;
import com.user.util.JsonUtils;
import com.user.util.JwtUtils;
import lombok.SneakyThrows;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.net.URLEncoder;
import java.util.*;

public class JwtLoginFilter extends AbstractAuthenticationProcessingFilter {
    private JwtProperties prop;
    public JwtLoginFilter(AuthenticationManager authenticationManager,JwtProperties prop){
        super(new AntPathRequestMatcher("/login"));
        setAuthenticationManager(authenticationManager);
        this.prop =prop;
    }
    @SneakyThrows
    @Override
    public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException {
        HashMap<String, Object> map = new HashMap<>();
        if(!"post".equalsIgnoreCase(request.getMethod())){
            map.put("message","请求方式错误！");
            resultResponse(response,map,HttpServletResponse.SC_UNAUTHORIZED);
            return null;
        }
        if(!Objects.equals(request.getContentType(),"application/json")){
            map.put("message","参数格式出错");
            resultResponse(response,map,HttpServletResponse.SC_UNAUTHORIZED);
            return null;
        }
        ServletInputStream inputStream=null;
        try {
            inputStream = request.getInputStream();
            StringBuilder stringBuilder = new StringBuilder();
            int len=0;
            byte[] b = new byte[1024];
            while ((len =inputStream.read(b))!=-1){
                stringBuilder.append(new String(b,0,len));
            }
            String s = stringBuilder.toString();
            Map<String, String> data = JsonUtils.toMap(s, String.class, String.class);
            UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(data.get("username"), data.get("password"));
            return getAuthenticationManager().authenticate(authenticationToken);
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            try {
                if(inputStream!=null){
                    inputStream.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        map.put("message","登录失败,用户名或密码出错");
        resultResponse(response,map,HttpServletResponse.SC_UNAUTHORIZED);
        return null;
    }

    @Override
    protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain, Authentication authResult) throws IOException, ServletException {
        String name = authResult.getName();
        Collection<? extends GrantedAuthority> authorities = authResult.getAuthorities();
        HashSet<Role> roles = new HashSet<>();
        Iterator<? extends GrantedAuthority> iterator = authorities.iterator();
        while (iterator.hasNext()){
            Role role = new Role(iterator.next().getAuthority());
            roles.add(role);
        }
        UserInfo userInfo = new UserInfo();
        userInfo.setUsername(name);
        userInfo.setGrantedAuthorities(roles);
        HashMap<String,Object> map = new HashMap<>();
        String token = JwtUtils.generateTokenExpireInSeconds(userInfo,prop.getPrivateKey(),prop.getTokenProper().getExpire());
        map.put("Authorization",token);
        resultResponse(response,map,HttpServletResponse.SC_OK);
    }

    private void resultResponse(HttpServletResponse response,Map<String,Object> data,int status) throws IOException {
        response.setContentType("application/json;charset=utf-8");
        response.setStatus(status);
        String result = JsonUtils.toString(data);
        PrintWriter writer = response.getWriter();
        writer.print(result);
        writer.flush();
        writer.close();
    }
}
